/**
 * This file is part of CommaTuner.
 * Copyright 2011 Gabriel G Mendonça (gabrielgmendonca@gmail.com)
 * 
 * CommaTuner is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * CommaTuner is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with CommaTuner.  If not, see <http://www.gnu.org/licenses/>.
 */

package br.mendonca.commatuner;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import br.mendonca.audio.analysis.Pitch;

/**
 * Updates the screen showing the detected pitch.
 * 
 * @author gmendonca
 */
public class PitchView extends View {

	private Pitch pitch = new Pitch(440, 1);

	private long lastTime;

	/**
	 * Constructor.
	 * 
	 * @param context
	 * @param attrs
	 */
	public PitchView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	/**
	 * Draws the tuner interface. Called by the Android framework when it's
	 * ready to draw this View.
	 */
	@Override
	protected void onDraw(Canvas canvas) {
		drawIndicator(canvas);
		drawText(canvas);

		measurePerformance();
	}

	/**
	 * Notifies the interface that the View must be updated with a new pitch.
	 * 
	 * @param pitch
	 *            The new pitch.
	 */
	public void update(Pitch pitch) {
		this.pitch = pitch;
		postInvalidate();

		Log.d("CommaTuner", pitch.toString());
	}

	private void drawIndicator(Canvas canvas) {
		Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
				R.drawable.black);

		int error = pitch.getError();
		float angle = 0.0f;
		if (error < 50.0f) {
			angle = error / 50.0f * 45.0f;
		} else {
			angle = (100.0f - error) / 50.0f * -45.0f;
		}

		Matrix matrix = new Matrix();
		matrix.postRotate(90.0f);
		matrix.postRotate(angle, (float) bitmap.getHeight() * -0.5f,
				(float) bitmap.getWidth());
		matrix.postTranslate((float) getWidth() / 2.0f,
				(float) getHeight() * 0.65f);

		Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
		canvas.drawBitmap(bitmap, matrix, paint);
	}

	private void drawText(Canvas canvas) {
		Paint paint = new Paint();
		paint.setColor(Color.WHITE);
		paint.setTextSize(20);

		int y = 40;
		canvas.drawText("Linear: " + pitch.toLinearSpace(), 20, y, paint);
		canvas.drawText("Out of tune (cents): " + pitch.getError(), 20, y + 20,
				paint);
		canvas.drawText("Scientific: " + pitch.toScientificNotation(), 20,
				y + 40, paint);
		canvas.drawText("Precision: " + pitch.precision + "Hz", 20, y + 60,
				paint);
	}

	private void measurePerformance() {
		long now = SystemClock.uptimeMillis();
		float delta = now - lastTime;
		float fps = 1.0f / delta * 1000.0f;
		Log.d("CommaTuner", "Interface time: " + delta);
		Log.d("CommaTuner", "Interface FPS: " + fps);

		lastTime = now;
	}
}
